#pragma once

#include "Socket.hpp"
#include "TcpServer.hpp"
#include "Util.hpp"
#include "Log.hpp"
#include <memory>
#include <iostream>
#include <cstring>
#include <unordered_map>
#include <functional>

using namespace SocketModule;
using namespace LogModule;

const std::string gspace = " ";
const std::string glinespace = "\r\n";
const std::string glinesep = ": ";

const std::string webroot = "./wwwroot";
const std::string homepage = "Index.html";
const std::string page_404 = "/404.html";


class HttpRequest
{
public:
    HttpRequest() : _is_interact(false)
    {
    }
    std::string Serialize()
    {
        return std::string();
    }
    void ParseReqLine(std::string &reqline)
    {

        // 具体工作过程->初始化字符串流：
        // std::stringstream ss(reqline) 创建一个字符串流对象 ss
        // 将 reqline 的内容加载到流中，就像它是一个输入源
        // 提取操作：
        // ss >> _method：从流中提取第一个"单词"（以空白字符分隔）到 _method
        // ss >> _uri：提取下一个"单词"到 _uri
        // ss >> _version：提取再下一个"单词"到 _version

        std::stringstream ss(reqline); // 使用reqline初始化字符串流,以空格作为分隔符,依次初始化>>后面的变量
        ss >> _method >> _uri >> _version;
    }
    bool Deserialize(std::string &reqstr)
    {
        std::cout << reqstr;
        // 1. 提取请求一行
        std::string reqline;
        bool res = Util::ReadOneLine(reqstr, &reqline, glinespace); // 提取reqstr里面\r\n前面的子串至变量reqline,同时删除reqstr里面已经提取出来的全部子串
        LOG(LogLevel::DEBUG) << reqline;

        std::cout << "\n";
        std::cout << reqstr;
        // 2. 对请求行反序列化
        ParseReqLine(reqline); // reqline里面存储的是客户端发过来的http报文"\r\n"前面的子串

        if (_uri == "/")
            _uri = webroot + _uri + homepage;
        else
            _uri = webroot + _uri;

        // if(_method == "POST")
        // {
        //     _is_interact = true;
        //     while(true)
        //     {
        //         Util::ReadOneLine(reqstr,&reqline,glinespace);
        //         if(reqline!=glinespace)
        //         {

        //         }
        //         else{
        //             break;
        //         }
        //     }
        // }       

        LOG(LogLevel::DEBUG) << "_method: " << _method;
        LOG(LogLevel::DEBUG) << "_uri: " << _uri;
        LOG(LogLevel::DEBUG) << "_version: " << _version;
         const std::string temp = "?";
        auto pos = _uri.find(temp);
        if (pos == std::string::npos)
        {
            return true;
        }
        _args = _uri.substr(pos + temp.size()); // 用户提交的参数,常见是账号及密码等
        _uri = _uri.substr(0, pos);
        _is_interact = true; // 需要交互
        return true;
    }
    std::string Uri() { return _uri; }
    bool isInteract() { return _is_interact; }
    std::string Args() {return _args;}
    ~HttpRequest()
    {
    }

private:
    std::string _method;
    std::string _uri;
    std::string _version;

    std::unordered_map<std::string, std::string> _headers;
    std::string _blankline;
    std::string _text;

    std::string _args;
    bool _is_interact;
};

class HttpResponse
{
public:
    HttpResponse() : _blankline(glinespace), _version("HTTP/1.0")
    {
    }
    std::string Serialize()
    {
        std::string status_line = _version + gspace + std::to_string(_code) + gspace + _desc + glinespace; // 状态行
        std::string resp_header;                                                                           // 响应包头
        for (auto &header : _headers)
        {
            std::string line = header.first + glinesep + header.second + glinespace;
            resp_header += line;
        }
        return status_line + resp_header + _blankline + _text;
    }
    void SetTargetFile(const std::string &target)
    {
        _target_file = target;
    }
    void SetCode(int code)
    {
        _code = code;
        switch (_code)
        {
        case 200:
            _desc = "OK";
            break;
        case 404:
            _desc = "NotFound";
            break;
        case 301:
            _desc = "Moved Permanently";
            break;
        case 302:
            _desc = "See Other"; // 状态描述变量
            break;
        default:
            break;
        }
    }
    void SetHeader(const std::string &key, const std::string &value)
    {
        auto iter = _headers.find(key);
        if (iter != _headers.end())
            return;
        _headers.insert(std::make_pair(key, value));
    }

    // 当浏览器请求一个文件时，服务器需要在 HTTP 响应头中设置 Content-Type: image/png，浏览器才能正确渲染 PNG 图片而非将其当作文本显示。
    // 若未正确设置 MIME 类型，可能导致文件无法正常解析（如下载而非预览）
    // Content-Type HTTP头是唯一权威的、声明内容类型的机制，文件后缀名只是一个辅助提示。
    std::string UriSuffix(const std::string &targetfile)
    {
        auto pos = targetfile.rfind(".");
        if (pos == std::string::npos)
        {
            return "text/html";
        }

        std::string suffix = targetfile.substr(pos);
        if (suffix == ".html" || suffix == ".htm")
            return "text/html";
        else if (suffix == ".jpg")
            return "iamge/jpeg";
        else if (suffix == "png")
            return "image/png";
        else
            return "";
    }

    bool MakeResponse()
    {
        if (_target_file == "./wwwroot/favicon.ico")
        {
            LOG(LogLevel::DEBUG) << "用户请求: " << _target_file << "忽略它";
            return false;
        }
        if (_target_file == "./wwwroot/redir_test")
        {
            // SetCode(302);
            SetCode(301);
            SetHeader("Location", "https://www.jingdong.com/");
            return true;
        }
        int filesize = 0;
        bool res = Util::ReadFileContent(_target_file, &_text);
        if (!res)
        {
            // _text = "";
            // LOG(LogLevel::WARNING) << "client want get: " << _target_file << " but not found";
            // SetCode(404);
            // _target_file = webroot + page_404;
            // filesize = Util::FileSize(_target_file);
            // Util::ReadFileContent(_target_file, &_text);
            // std::string suffix = UriSuffix(_target_file);
            // SetHeader("Content-Type", suffix);
            // SetHeader("Content_Length", std::to_string(filesize));
            SetCode(302);
            SetHeader("Location", "http://121.37.20.172:8080/404/html"); // 实现重定向
            return true;
        }
        else
        {
            LOG(LogLevel::DEBUG) << "读取文件: " << _target_file;
            SetCode(200);
            filesize = Util::FileSize(_target_file);
            std::string suffix = UriSuffix(_target_file);
            SetHeader("Content-Type", suffix);
            SetHeader("Content_Length", std::to_string(filesize));
            SetHeader("Set-Cookie","username=lisi;");
            //SetHeader("Set-Cookie","passwd=123456;");
        }
        return true;
    }
    void SetText(const std::string &t)
    {
        _text = t;
    }
    bool Deserialize(std::string &reqstr)
    {
        return true;
    }
    ~HttpResponse()
    {
    }

    // private:
public:
    std::string _version;
    int _code;
    std::string _desc;

    std::unordered_map<std::string, std::string> _headers;
    std::string _blankline;
    std::string _text;

    std::string _target_file;
};


using http_func_t = std::function<void(HttpRequest &req, HttpResponse &resp)>;

class Http
{
public:
    Http(uint16_t port) : tsvrp(std::make_unique<TcpServer>(port))
    {
    }
    void HandlerHttpRequest(std::shared_ptr<Socket> &sock, InetAddr &clinet)
    {
        std::string httpreqstr;
        int n = sock->Recv(&httpreqstr);
        if (n > 0)
        {
            HttpRequest req;
            HttpResponse resp;
            req.Deserialize(httpreqstr); // 对从客户端发过来的报文进行反序列化
            if (req.isInteract())
            {
                if(_route.find(req.Uri()) == _route.end())
                {
                  //SetCode(302);  
                }
                else
                {
                    _route[req.Uri()](req,resp);
                    std::string response_str = resp.Serialize();
                    sock->Send(response_str);
                }
            }
            else
            {
                resp.SetTargetFile(req.Uri());
                if (resp.MakeResponse())
                {
                    std::string response_str = resp.Serialize();
                    sock->Send(response_str);
                }
            }
            // HttpResponse resp;
            // resp._version = "HTTP/1.1";
            // resp._code = 200;
            // resp._desc = "OK";

            // LOG(LogLevel::DEBUG) << "用户请求: " << filename;

            // bool res = Util::ReadFileContent(filename, &(resp._text));
            // std::string response_str = resp.Serialize();
            // sock->Send(response_str);
        }

// #ifndef DEBUG
// #define DEBUG
#ifndef DEBUG
        // std::string httpreqstr;
        sock->Recv(&httpreqstr);
        std::cout << httpreqstr;

        HttpResponse resp;
        resp._version = "HTTP/1.1";
        resp._code = 200;
        resp._desc = "OK";

        std::string filename = webroot + homepage;
        bool res = Util::ReadFileContent(filename, &(resp._text));
        (void)res;

        std::string response_str = resp.Serialize();
        sock->Send(response_str);

#endif
    }
    void Start()
    {
        tsvrp->Start([this](std::shared_ptr<Socket> &sock, InetAddr &client)
                     { this->HandlerHttpRequest(sock, client); });
    }
    void RegisterService(const std::string name, http_func_t h)
    {
        std::string key = webroot + name;
        auto iter = _route.find(key);
        if (iter == _route.end())
        {
            _route.insert(std::make_pair(key, h));
        }
    }
    ~Http() {}

private:
    std::unique_ptr<TcpServer> tsvrp;
    std::unordered_map<std::string, http_func_t> _route;
};